﻿using B.S.BasicData.Api.Read.Application.Command.Account;
using B.S.BasicData.Api.Read.DTOs;
using B.S.BasicData.Api.Read.Extensions;
using B.S.BasicData.Domain.Entities;
using B.S.BasicData.ErrorCode;
using B.S.BasicData.Infrastructure.Interface;
using MediatR;

namespace B.S.BasicData.Api.Read.Application.Handler.Account
{

    /// <summary>
    /// 刷新访问token的处理类
    /// </summary>
    public class RefreshTokenHander : IRequestHandler<RefreshTokenCommand, ApiResult<AccountDTO>>
    {


        private readonly IBaseRepository<AccountModel> accountRepo;
        private readonly IBaseRepository<RoleModel> roleRepo;
        private readonly IBaseRepository<AccountRoleModel> accountRoleRepo;

        /// <summary>
        /// 注入仓储
        /// </summary>
        /// <param name="accountRepo">账号仓储</param>
        /// <param name="roleRepo">角色仓储</param>
        /// <param name="accountRoleRepo">账号角色仓储</param>
        public RefreshTokenHander(IBaseRepository<AccountModel> accountRepo, IBaseRepository<RoleModel> roleRepo, IBaseRepository<AccountRoleModel> accountRoleRepo)
        {
            this.accountRepo = accountRepo;
            this.roleRepo = roleRepo;
            this.accountRoleRepo = accountRoleRepo;
        }

        /// <summary>
        /// 刷新访问token的处理方法
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<ApiResult<AccountDTO>> Handle(RefreshTokenCommand request, CancellationToken cancellationToken)
        {// 刷新访问token的处理方法

            ApiResult<AccountDTO> res = new ApiResult<AccountDTO>(); //实例化响应包装类
            
            var account = accountRepo.GetAll().Where(x => x.RefreshToken == request.RefreshToken&&x.FingerPoint==request.FingerPoint).FirstOrDefault();//根据刷新token 和登录时录入的指纹 查询账号
            if (account == null)
            { //没有找到账号,直接返回失败的响应包装类对象
                res.Code = ApiEnum.Failed;
                res.Msg = "刷新token无效或者伪造了客户端指纹!";
                return  res;
            }
            if (account.RefreshTokenTime.AddMinutes(15) < DateTime.Now) {//当前时间大于过期时间,说明已经过期
                res.Code = ApiEnum.Failed;
                res.Msg = "刷新token已经过期!";
                return res;
            }
            //登录成功,给账号查找角色
            var accRole = accountRoleRepo.GetAll().Where(x => x.AccountId == account.Id).FirstOrDefault();//根据账号id,查找账号角色关系
            if (accRole == null)
            {
                res.Code = ApiEnum.Failed;
                res.Msg = "请联系管理员给账号配置角色!";
                return res;
            }
            var role = await roleRepo.GetModel(accRole.RoleId);
            if (role == null)
            {
                res.Code = ApiEnum.Failed;
                res.Msg = "请联系管理员配置角色!";
                return res;
            }
            var refreshToken = this.CreateFreshToken();//生成一个刷新token,要求token唯一且加密
            //实例化账号DTO
            var accountDto = new AccountDTO()
            {
                AccountName = account.AccountName,
                RoleName = role.RoleName,
                RealName = account.RealName,
                JwtToken = this.CreateTokenString(account.AccountName, role.RoleName, account.RealName),
                RefreshToken = refreshToken
            };
            account.RefreshToken = refreshToken; //给用户保存刷新token
            account.RefreshTokenTime = DateTime.Now; //新的刷新token创建的时候
            account.FingerPoint = request.FingerPoint; //录入刷新token的指纹

            //把账号信息保存到数据库  调用了UpdateAsync方法,意思是把刷新token 时间 还有指纹存到数据库
            await accountRepo.UpdateAsync(account);

            res.Code = ApiEnum.Success;
            res.Msg = "恭喜您,刷新访问token成功!";
            res.Data = accountDto;

            return res;

        }
    }
}
